package com.ruoyi.web.core.service;

import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.net.domain.NetElement;
import com.ruoyi.net.domain.Performance;
import com.ruoyi.net.domain.SysPerformanceInfo;
import com.ruoyi.net.service.INetElementService;
import com.ruoyi.net.service.IPerformanceService;
import com.ruoyi.net.utils.Pm;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import oshi.util.Util;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
//@EnableScheduling
public class FtpLogMonitor {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    //    @Value("${ftp.logPath}")
    private String LOG_FILE_PATH;// = "C:\\Program Files (x86)\\FileZilla Serve 中文版\\Logs";//\\FileZilla Server.log";
    //    @Value("${ftp.homePath}")
    private String LOG_FILE_PRE;// = "E:\\spn\\ftp";
    //    @Value("${ftp.pmFileType}")
    private String PM_FILE_SUFFIX;// = ".dat";
    // 正则表达式用于匹配客户端 IP 地址和文件传输信息
    private static final Pattern IP_PATTERN = Pattern.compile("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})");
    //    private static final Pattern FILE_TRANSFER_PATTERN = Pattern.compile("(STOR|RETR) (.*)");
    private static final Pattern FILE_TRANSFER_PATTERN = Pattern.compile("(226 Successfully transferred) (.*)");
    private Collection<String> keys = new ArrayList<>();


    @Autowired
    private INetElementService netElementService;

    @Autowired
    private IPerformanceService performanceService;

    @Autowired
    private RedisCache redisCache;

    //    @Scheduled(fixedRate = 3000) // 每 3 秒执行一次
    public void monitorLog() {
        // 网元设备列表
        keys = redisCache.keys(CacheConstants.NET_ELEMENT_KEY + "*");
        File logFile = FileUtils.getLatestFile(LOG_FILE_PATH, ".log");
        while (true) {
            // 读取上次记录的行号
            int lastLineNumber = StringUtils.isNull(redisCache.getCacheObject("lastLineNumber")) ? 0 : Integer.parseInt(redisCache.getCacheObject("lastLineNumber").toString());
            if (logFile != null && logFile.exists()) {
                try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) {
                    // 跳过已经读取过的行
                    for (int i = 0; i < lastLineNumber; i++) {
                        reader.readLine();
                    }
                    String line;
                    while ((line = reader.readLine()) != null) {
                        // 匹配客户端 IP 地址
                        Matcher ipMatcher = IP_PATTERN.matcher(line);
                        if (ipMatcher.find()) {
                            String clientIp = ipMatcher.group(1);
                            // 匹配文件传输信息
                            Matcher fileTransferMatcher = FILE_TRANSFER_PATTERN.matcher(line);
                            if (fileTransferMatcher.find()) {
//                                String operation = fileTransferMatcher.group(1);
                                String fileName = fileTransferMatcher.group(2); // 去掉引号，转换文件目录连接符号
//                                logger.info("FTP客户端 " + clientIp + " 执行了 " + operation + " 操作，文件名：" + fileName);

                                // 拿到ip和文件路径
                                // 开始解析
                                String filePath = LOG_FILE_PRE + fileName.replaceAll("/", "\\\\").replaceAll("\"", "");
                                // 读取性能文件
                                readData(filePath, clientIp);
                            }
                        }
                        lastLineNumber++;
                        Util.sleep(550);
                    }
                    // 更新最后读取的行号
                    redisCache.setCacheObject("lastLineNumber", lastLineNumber - 1);
                } catch (Exception e) {
                    logger.error("读取FTP性能文件异常：" + e.getMessage());
                }

            }
            Util.sleep(800);
        }
    }

    /**
     * 读取并解析性能文件，入库
     *
     * @param filePath
     * @param clientIp
     */
    private void readData(String filePath, String clientIp) {
        // 判断是否性能文件
        if (!filePath.toLowerCase().endsWith(".dat")) {
            return;
        }
        File originalFile = new File(filePath);
        if (!originalFile.exists()) {
            return;
        }
        try (FileInputStream fis = new FileInputStream(originalFile)) {
            // 创建一个字节数组来存储文件内容
            byte[] buffer = new byte[fis.available()];
            // 读取文件内容到字节数组
            fis.read(buffer);
            // 从PB数据开始
            Pm.NePmHead nePmHead = Pm.NePmHead.parseFrom(buffer);
            logger.info("性能数据开始============");
            logger.info(nePmHead.toString());
            logger.info("性能数据============结束");

            /*File newFile = new File(originalFile.getAbsolutePath() + ".bak");
            // 修改文件名称
            if (originalFile.renameTo(newFile)) {
                logger.info(newFile.getName() + "文件名称修改成功");
            } else {
                logger.info(newFile.getName() + "文件名称修改失败");
            }*/
            String elementId = "";
            // 通过ip查找网元id
            for (String key : keys) {
                NetElement netElement = netElementService.getCacheObject(key.replaceAll(CacheConstants.NET_ELEMENT_KEY, ""));
                if (netElement != null && clientIp.equals(netElement.getIp())) {
                    elementId = netElement.getId();
                    break;
                }
            }
//            logger.info("FTP读取设备elementId:" + elementId);
            if (StringUtils.isNotEmpty(elementId)) {
                List<Pm.BoardPm> boardPmList = nePmHead.getBrdPmList();
                List<Performance> performances = new ArrayList<>();
                for (Pm.BoardPm boardPm : boardPmList) {
                    String time = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date(boardPm.getTime() * 1000L));
                    List<Pm.PmItem> pmVectors = boardPm.getPmVectorList();
                    for (Pm.PmItem pmItem : pmVectors) {
                        Performance pm = new Performance();
                        pm.setSource(nePmHead.getQueryId()); // 源
                        pm.setElementId(elementId);
                        pm.setStartTime(time); // 时间
                        pm.setLineNo(pmItem.getLine().getTag() + ""); // 线路号
                        pm.setObjName(pmItem.getLine().getLocateSrcString().toString()); // 对象
                        List<Pm.PmValueItem> pmValueItemList = pmItem.getItemList();
                        // 性能分组
                        Map<Integer, List<Pm.PmValueItem>> groupedMap = groupByCode(pmValueItemList);
                        // 分组信息入库
                        for (Map.Entry<Integer, List<Pm.PmValueItem>> entry : groupedMap.entrySet()) {
                            pm.setRemark(entry.getKey() + ""); // 备注，方便以后排查没有找到编码的
                            SysPerformanceInfo performanceInfo = redisCache.getCacheObject(CacheConstants.PERFORMANCE_INFO_KEY + entry.getKey());
                            String unit = "";
                            if (performanceInfo != null) {
                                pm.setEnglishCode(performanceInfo.getPmEn()); // 性能英文代码
                                pm.setCode(performanceInfo.getPmCn()); // 性能代码
                                unit = performanceInfo.getPmUnit(); // 单位
                            }
                            for (Pm.PmValueItem pmValueItem : entry.getValue()) {
                                String pmValueStr = "0" + " " + unit;
                                // tag = 0 时，性能值为 0
                                if (pmValueItem.getValue().getTag() == 1) {
                                    pmValueStr = bytesToBinaryString(pmValueItem.getValue().getValue().toByteArray(), 0, pmValueItem.getValue().getLength()) + " " + unit;
                                }
                                if (0 == pmValueItem.getPmType()) {
                                    pm.setCurrentValue(pmValueStr); // 当前

                                } else if (1 == pmValueItem.getPmType()) {
                                    pm.setMaxValue(pmValueStr); // 最大
                                } else if (2 == pmValueItem.getPmType()) {
                                    pm.setMinValue(pmValueStr); // 最小
                                } else if (3 == pmValueItem.getPmType()) {
                                    pm.setMiddleValue(pmValueStr); // 平均
                                }
                            }

                            pm.setCreateBy("admin");
                            pm.setCreateTime(new Date(boardPm.getTime() * 1000L));
                            // 假如 ip 和 性能代码
                            pm.setRemark(clientIp + "_" + pm.getRemark());
                            pm.setId(IdUtils.simpleUUID());
                            //if (!pm.getCurrentValue().startsWith("0 ")) {
                            //    performances.add(pm);
                            //}
                            performances.add(pm);
                        }
                        /*
                        for (Pm.PmValueItem pmValueItem : pmValueItemList) {
//                            pm.setCode(pmValueItem.getCode() + ""); // 性能代码
                            pm.setRemark(pmValueItem.getCode() + ""); // 备注，方便以后排查没有找到编码的
                            SysPerformanceInfo performanceInfo = redisCache.getCacheObject(CacheConstants.PERFORMANCE_INFO_KEY + pmValueItem.getCode());
                            String unit = "";
                            if (performanceInfo != null) {
                                pm.setEnglishCode(performanceInfo.getPmEn()); // 性能英文代码
                                pm.setCode(performanceInfo.getPmCn()); // 性能代码
                                unit = performanceInfo.getPmUnit(); // 单位
                            }
                            String pmValueStr = "0" + " " + unit;
                            // tag = 0 时，性能值为 0
                            if (pmValueItem.getValue().getTag() == 1) {
                                pmValueStr = bytesToBinaryString(pmValueItem.getValue().getValue().toByteArray(), 0, pmValueItem.getValue().getLength()) + " " + unit;
                            }
                            if (0 == pmValueItem.getPmType()) {
                                pm.setCurrentValue(pmValueStr); // 当前

                            } else if (1 == pmValueItem.getPmType()) {
                                pm.setMaxValue(pmValueStr); // 最大
                            } else if (2 == pmValueItem.getPmType()) {
                                pm.setMinValue(pmValueStr); // 最小
                            } else if (3 == pmValueItem.getPmType()) {
                                pm.setMiddleValue(pmValueStr); // 平均
                            }
                        }
                        pm.setCreateBy("admin");
                        pm.setCreateTime(new Date(boardPm.getTime() * 1000L));
                        pm.setRemark(clientIp + "_" + pm.getRemark());
                        pm.setId(IdUtils.simpleUUID());
//                        if (!pm.getCurrentValue().startsWith("0 ")) {
//                            performances.add(pm);
//                        }
                        performances.add(pm);
                        */
                    }

                }
                if (performances.size() > 0) {
                    performanceService.insertPerformances(performances);
                    logger.info("FTP dat数据入库条数:" + performances.size());
                }
            } else {
                logger.info("FTP读取设备elementId为空");
            }

        } catch (Exception e) {
            logger.error("解析性能文件时出现错误," + clientIp + ", " + originalFile.getAbsolutePath() + ": " + e.getMessage());
        }
    }

    /**
     * 将字节转换成long
     *
     * @param bytes
     * @return
     */
    public static long parseByteArray(byte[] bytes) {
        long result = 0;
        for (int i = 0; i < bytes.length; i++) {
            // 去掉符号，将当前字节左移相应的位数
            result |= ((long) (bytes[i] & 0xff)) << ((bytes.length - 1 - i) * 8);
        }
        return result;
    }

    /**
     * 监控FTP
     */
    public void startMonitor() {
        monitorLog();
        /*
        try {
            // 创建服务器Socket，监听21端口
            ServerSocket serverSocket = new ServerSocket(21);
            System.out.println("FTP Server is running on port 21...");
            while (true) {
                try {
                    monitorFtpPort(serverSocket);
                }
                catch (Exception e) {
                    logger.error("FTP端口监控出现错误: " + e.getMessage());
                }
                Util.sleep(800);
            }
        }
        catch (IOException e) {
            logger.error("FTP端口监控出现错误: " + e.getMessage());
        }
        */
    }

    private void monitorFtpPort(ServerSocket serverSocket) throws Exception {
        // 等待客户端连接
        Socket clientSocket = serverSocket.accept();
        System.out.println("Client connected: " + clientSocket.getInetAddress());
        // 获取输入流和输出流
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        // 读取客户端发送的数据
        String line;
        while ((line = in.readLine()) != null) {
            System.out.println("Received from client: " + line);
            // 这里可以添加处理逻辑，根据接收到的命令进行相应的操作
            // 匹配客户端 IP 地址
            Matcher ipMatcher = IP_PATTERN.matcher(line);
            if (ipMatcher.find()) {
                String clientIp = ipMatcher.group(1);
                // 匹配文件传输信息
                Matcher fileTransferMatcher = FILE_TRANSFER_PATTERN.matcher(line);
                if (fileTransferMatcher.find()) {
                    String operation = fileTransferMatcher.group(1);
                    String fileName = fileTransferMatcher.group(2);
                    logger.info("FTP客户端 " + clientIp + " 执行了 " + operation + " 操作，文件名：" + fileName);

                    // 拿到ip和文件路径
                    // 开始解析
                    String filePath = LOG_FILE_PRE + fileName.replaceAll("/", "\\\\").replaceAll("\"", "");
                    // 读取性能文件
                    readData(filePath, clientIp);
                }
            }
        }

        // 关闭资源
        in.close();
        out.close();
        clientSocket.close();

    }


    /**
     * 去掉收尾 0
     * 截取部分字节
     * @param arr
     * @param startIndex
     * @param endIndex
     * @return
     */
    public byte[] trimZeroBytes(byte[] arr, int startIndex, int endIndex) {
        if (arr == null || arr.length == 0) {
            return arr;
        }
        return Arrays.copyOfRange(arr, startIndex, endIndex);
        /*int start = 0;
        // 找出头部第一个不为 0 的元素的索引
        while (start < arr.length && arr[start] == 0) {
            start++;
        }
        int end = arr.length - 1;
        // 找出尾部第一个不为 0 的元素的索引
        while (end >= start && arr[end] == 0) {
            end--;
        }
        // 根据首尾索引截取数组
        return Arrays.copyOfRange(arr, start, end + 1);*/
    }

    /**
     * 字节数组转浮点型 字符串
     *
     * @param bytes
     * @param strartIndex
     * @param endIndex
     * @return
     */
    public String bytesToBinaryString(byte[] bytes, int strartIndex, int endIndex) {
        byte[] trimmedBytes = trimZeroBytes(bytes, strartIndex, endIndex);
        if (trimmedBytes == null || trimmedBytes.length == 0) {
            return "0";
        }
        StringBuilder binaryString = new StringBuilder();
        for (byte b : trimmedBytes) {
            // 将字节转换为 8 位二进制字符串
            String byteBinary = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
            binaryString.append(byteBinary);
        }
//        return binaryString.toString();
        if (endIndex == 4) {
            // 将二进制字符串转换为整数
            int intValue = Integer.parseUnsignedInt(binaryString.toString(), 2);

            // 将整数解析为浮点数
            float floatValue = Float.intBitsToFloat(intValue);
            if (Float.isNaN(floatValue)) {
                return "0";
            }
            return String.valueOf(floatValue);
        } else {
            // 将二进制字符串转换为长整数
            long longBits = Long.parseUnsignedLong(binaryString.toString(), 2);

            // 将长整数转换为双精度浮点数
            double doubleValue = Double.longBitsToDouble(longBits);
            if (Double.isNaN(doubleValue)) {
                return "0";
            }
            return String.valueOf(doubleValue);
        }
    }

    // 从字节数组读取16位短整数（大端序）
    public static short readShortBE(byte[] bytes, int offset) {
        return (short) (((bytes[offset] & 0xFF) << 8) |
                (bytes[offset + 1] & 0xFF));
    }

    // 从字节数组读取16位短整数（小端序）
    public static short readShortLE(byte[] bytes, int offset) {
        return (short) (((bytes[offset + 1] & 0xFF) << 8) |
                (bytes[offset] & 0xFF));
    }


    /**
     * 将性能列表进行分组处理
     * @param oriList
     * @return
     */
    private Map<Integer, List<Pm.PmValueItem>> groupByCode(List<Pm.PmValueItem> oriList) {
        Map<Integer, List<Pm.PmValueItem>> result = new HashMap<>();
        for (Pm.PmValueItem item : oriList) {
            result.computeIfAbsent(item.getCode(), k -> new ArrayList<>())
                    .add(item);
        }
        return result;
    }
}